# -*- coding: utf-8 -*-

# Copyright (c) 2015, Sergio Callegari
# All rights reserved.

# This file is part of PyDSM.

# PyDSM is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# PyDSM is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with PyDSM.  If not, see <http://www.gnu.org/licenses/>.

"""
Monkey patch Sphinx, in order to fix some issues with LaTeX builds

* Restrict the tex_replacement table, to stop escaping Greek letters.
  * These are much better supported with the textgreek package.
  * Converting Greek text to math causes issues with hyperref when Greek
    letters occur in section headings.
  * Converting Greek text to math makes it impossible to make it follow
    the formatting of the surrounding text *eg. bold, italics, etc).
  * Note that this change also requires the unicode option to be passed to
    hyperref

* Use tabu package in conjunction with longtable to support multi page
  tables.
  * Namely use the longtabu environment in place of longable.
  * The longtabu environment also supports tabularx features such as the
    possibility of having automatically sized paragraph type columns.  This
    is needed by autosummary tables to avoid overfull boxes in the
    function descriptions.

* Have autosummary use the new column types supported by tabu
"""


from sphinx.locale import _
from sphinx.util import texescape
from sphinx.writers import latex
from sphinx.ext import autosummary
from sphinx import addnodes
from docutils import nodes
from docutils.statemachine import ViewList


texescape.tex_replacements = [
    # map TeX special chars
    (u'$', ur'\$'),
    (u'%', ur'\%'),
    (u'&', ur'\&'),
    (u'#', ur'\#'),
    (u'_', ur'\_'),
    (u'{', ur'\{'),
    (u'}', ur'\}'),
    (u'[', ur'{[}'),
    (u']', ur'{]}'),
    (u'`', ur'{}`'),
    (u'\\', ur'\textbackslash{}'),
    (u'~', ur'\textasciitilde{}'),
    (u'<', ur'\textless{}'),
    (u'>', ur'\textgreater{}'),
    (u'^', ur'\textasciicircum{}'),
    # map special Unicode characters to TeX commands
    (u'¶', ur'\P{}'),
    (u'§', ur'\S{}'),
    (u'€', ur'\texteuro{}'),
    (u'∞', ur'\(\infty\)'),
    (u'±', ur'\(\pm\)'),
    (u'→', ur'\(\rightarrow\)'),
    (u'‣', ur'\(\rightarrow\)'),
    # used to separate -- in options
    (u'\ufeff', ur'{}'),
    # map some special Unicode characters to similar ASCII ones
    (u'─', ur'-'),
    (u'⎽', ur'\_'),
    (u'╲', ur'\textbackslash{}'),
    (u'|', ur'\textbar{}'),
    (u'│', ur'\textbar{}'),
    (u'ℯ', ur'e'),
    (u'ⅈ', ur'i'),
    (u'₁', ur'1'),
    (u'₂', ur'2')]

latex.LaTeXTranslator.default_elements['longtable'] = (
    r'\usepackage{longtable}' + '\n' +
    r'\usepackage{tabu}')

latex.HEADER = r'''%% Generated by Sphinx.
\def\sphinxdocclass{%(docclass)s}
\documentclass[%(papersize)s,%(pointsize)s%(classoptions)s]{%(wrapperclass)s}
%(inputenc)s
%(utf8extra)s
%(cmappkg)s
%(fontenc)s
%(babel)s
%(fontpkg)s
%(fncychap)s
%(longtable)s
\usepackage{sphinx}
\usepackage{multirow}
%(preamble)s

\title{%(title)s}
\date{%(date)s}
\release{%(release)s}
\author{%(author)s}
\newcommand{\sphinxlogo}{%(logo)s}
\renewcommand{\releasename}{%(releasename)s}
%(makeindex)s
'''


def depart_table(self, node):
    if self.table.rowcount > 30:
        self.table.longtable = True
    self.body = self._body
    if not self.table.longtable and self.table.caption is not None:
        self.body.append(u'\n\n\\begin{threeparttable}\n'
                         u'\\capstart\\caption{%s}\n' % self.table.caption)
    if self.table.longtable:
        self.body.append('\n{\\tabulinesep=0.5ex%\n\\begin{longtabu}')
        endmacro = '\\end{longtabu}}\n\n'
    elif self.table.has_verbatim:
        self.body.append('\n\\begin{tabular}')
        endmacro = '\\end{tabular}\n\n'
    elif self.table.has_problematic and not self.table.colspec:
        # if the user has given us tabularcolumns, accept them and use
        # tabulary nevertheless
        self.body.append('\n\\begin{tabular}')
        endmacro = '\\end{tabular}\n\n'
    else:
        self.body.append('\n\\begin{tabulary}{\\linewidth}')
        endmacro = '\\end{tabulary}\n\n'
    if self.table.colspec:
        self.body.append(self.table.colspec)
    else:
        if self.table.has_problematic:
            colwidth = 0.95 / self.table.colcount
            colspec = ('p{%.3f\\linewidth}|' % colwidth) * self.table.colcount
            self.body.append('{|' + colspec + '}\n')
        elif self.table.longtable:
            self.body.append('{|' + ('l|' * self.table.colcount) + '}\n')
        else:
            self.body.append('{|' + ('L|' * self.table.colcount) + '}\n')
    if self.table.longtable and self.table.caption is not None:
        self.body.append(u'\\caption{%s} \\\\\n' % self.table.caption)
    if self.table.caption is not None:
        for id in self.next_table_ids:
            self.body.append(self.hypertarget(id, anchor=False))
        self.next_table_ids.clear()
    if self.table.longtable:
        self.body.append('\\hline\n')
        self.body.extend(self.tableheaders)
        self.body.append('\\endfirsthead\n\n')
        self.body.append('\\multicolumn{%s}{c}%%\n' % self.table.colcount)
        self.body.append(r'{{\textsf{\tablename\ \thetable{} -- %s}}} \\'
                         % _('continued from previous page'))
        self.body.append('\n\\hline\n')
        self.body.extend(self.tableheaders)
        self.body.append('\\endhead\n\n')
        self.body.append((ur'\hline \multicolumn{%s}{|r|}{{\textsf{%s}}}'
                          ur'\\ \hline') % (self.table.colcount,
                         _('Continued on next page')))
        self.body.append('\n\\endfoot\n\n')
        self.body.append('\\endlastfoot\n\n')
    else:
        self.body.append('\\hline\n')
        self.body.extend(self.tableheaders)
    self.body.extend(self.tablebody)
    self.body.append(endmacro)
    if not self.table.longtable and self.table.caption is not None:
        self.body.append('\\end{threeparttable}\n\n')
    self.table = None
    self.tablebody = None

latex.LaTeXTranslator.depart_table = depart_table


autosummary_table = autosummary.autosummary_table


def get_table(self, items):
    """Generate a proper list of table nodes for autosummary:: directive.

    *items* is a list produced by :meth:`get_items`.
    """
    table_spec = addnodes.tabular_col_spec()
    table_spec['spec'] = 'lX[,l]'

    table = autosummary_table('')
    real_table = nodes.table('', classes=['longtable'])
    table.append(real_table)
    group = nodes.tgroup('', cols=2)
    real_table.append(group)
    group.append(nodes.colspec('', colwidth=10))
    group.append(nodes.colspec('', colwidth=90))
    body = nodes.tbody('')
    group.append(body)

    def append_row(*column_texts):
        row = nodes.row('')
        for text in column_texts:
            node = nodes.paragraph('')
            vl = ViewList()
            vl.append(text, '<autosummary>')
            self.state.nested_parse(vl, 0, node)
            try:
                if isinstance(node[0], nodes.paragraph):
                    node = node[0]
            except IndexError:
                pass
            row.append(nodes.entry('', node))
        body.append(row)

    for name, sig, summary, real_name in items:
        qualifier = 'obj'
        if 'nosignatures' not in self.options:
            col1 = ':%s:`%s <%s>`\ %s' % (qualifier, name, real_name, sig)
        else:
            col1 = ':%s:`%s <%s>`' % (qualifier, name, real_name)
        col2 = summary
        append_row(col1, col2)

    return [table_spec, table]

autosummary.Autosummary.get_table = get_table


def setup(app):
    pass
